package com.xc.stock.domain.basic.service;

import java.math.BigDecimal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.xc.stock.constant.AccountLogType;
import com.xc.stock.domain.basic.entity.Account;
import com.xc.stock.domain.basic.entity.AccountAction;
import com.xc.stock.domain.basic.entity.AccountLog;
import com.xc.stock.domain.basic.factory.AccountActionFactory;
import com.xc.stock.domain.basic.repository.AccountActionRepository;
import com.xc.stock.dto.model.AccountInfo;
import com.xc.stock.dto.model.AccountOperParam;
import com.xc.stock.enhance.eventbus.EventBusListener;
import com.xc.stock.utils.SpringUtils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * AccountActionService
 *
 * @author xlfd
 * @email xlfd@gmail.com
 * @created 2022/03/25
 */
@Slf4j
@Service
@EventBusListener
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AccountActionService {
	final AccountActionRepository repository;
	final AccountActionFactory factory;
	final AccountLogService accountLogService;

	public AccountActionRepository repository() {
		return repository;
	}

	public static AccountActionService of() {
		return SpringUtils.getBean(AccountActionService.class);
	}
	
//	@Subscribe
//	public void e(UserRemovedEvent e) {
//		Utils.t().exec(status -> {
//			QAccountActionPO q = QAccountActionPO.accountActionPO;
//			long row = repository.update(q)
//					.set(q.status, StatusEnum.DISABLE.v())
//					.where(q.role.eq(RoleEnum.USER.code()))
//					.where(q.destId.eq(String.valueOf(e.getUser().getId())))
//					.execute();
//			
//			log.info("AccountActionService=>UserRemovedEvent[{}] execute row: {} ", e.getUser().thumb(), row);
//		});
//	}
	
	public AccountInfo actionDirectly(Account account, AccountLogType accountLogType, BigDecimal amount,
			JSONObject pre, JSONObject after, AccountOperParam accountOperParam) {
		AccountAction aa = factory.from(account, accountLogType, amount, accountOperParam);
		aa.finish(amount);
		repository().save(aa);
		AccountLog l = accountLogService.log(aa.getId(), accountLogType, account, amount, pre, after, accountOperParam);
		return AccountInfo.builder()
				.action(aa)
				.log(l)
				.build();
	}
	
	public AccountInfo actionLock(Account account, AccountLogType accountLogType, BigDecimal amount,
			JSONObject pre, JSONObject after, AccountOperParam accountOperParam) {
		AccountAction aa = factory.from(account, accountLogType, amount, accountOperParam);
		repository().save(aa);
		
		AccountLog l = accountLogService.log(aa.getId(), accountLogType, account, amount, pre, after, accountOperParam);
		return AccountInfo.builder()
				.action(aa)
				.log(l)
				.build();
	}
	
	public AccountInfo actionLockHandleSuccessful(Account account, AccountLogType accountLogType, BigDecimal amount,
			JSONObject pre, JSONObject after, Integer actionId) {
		AccountAction aa = repository().findById(actionId).orElse(null);
		if(aa == null) {
			log.error("actionLockHandleSuccessful 找不到AccountAction-ID: {}", actionId);
			return null;
		}
		
		aa.finish(amount);
		repository().save(aa);
		
		AccountOperParam accountOperParam = aa.accountOperParam();
		accountOperParam.setLogContent(Joiner.on("-").join(accountOperParam.getLogContent(), "成功"));
		
		AccountLog l = accountLogService.log(aa.getId(),accountLogType, account, amount, pre, after, accountOperParam);
		return AccountInfo.builder()
				.action(aa)
				.log(l)
				.build();
	}
	
	public AccountInfo actionLockHandleRefund(Account account, AccountLogType accountLogType, BigDecimal amount,
			JSONObject pre, JSONObject after, Integer actionId) {
		AccountAction aa = repository().findById(actionId).orElse(null);
		if(aa == null) {
			log.error("actionLockHandleSuccessful 找不到AccountAction-ID: {}", actionId);
			return null;
		}
		
		aa.refund(amount, null);
		repository().save(aa);
		
		AccountOperParam accountOperParam = aa.accountOperParam();
		accountOperParam.setLogContent(Joiner.on("-").join(accountOperParam.getLogContent(), "退款"));
		
		AccountLog l = accountLogService.log(aa.getId(),accountLogType, account, amount.negate(), pre, after, accountOperParam);
		return AccountInfo.builder()
				.action(aa)
				.log(l)
				.build();
	}
	
	public AccountInfo actionLockHandleFail(Account account, AccountLogType accountLogType, BigDecimal amount,
			JSONObject pre, JSONObject after, Integer actionId, String failMsg) {
		AccountAction aa = repository().findById(actionId).orElse(null);
		if(aa == null) {
			log.error("actionLockHandleSuccessful 找不到AccountAction-ID: {}", actionId);
			return null;
		}
		
		aa.refund(amount, failMsg);
		repository().save(aa);
		
		AccountOperParam accountOperParam = aa.accountOperParam();
		accountOperParam.setLogContent(Joiner.on("-").join(accountOperParam.getLogContent(), failMsg));
		
		AccountLog l = accountLogService.log(aa.getId(), accountLogType, account, amount, pre, after, accountOperParam);
		return AccountInfo.builder()
				.action(aa)
				.log(l)
				.build();
	}
}
